1. Introducció

L’objectiu d’aquesta anàlisi és comparar diferents models predictius per poder determinar la polaritat d’un Tweet. En concret ens interessarà saber si un determinat Tweet és positiu o no partint de les paraules que el componen. La variable dependent a predir serà una variable qualitativa (POSITIU) i que es tractarà com un factor de dos possibles valors (V / F). Les variables independents seran el conjunt de paraules que formen els diferents Tweets que utilitzarem. Indicar que els Tweets que s’analitzarem seran en castellà i que en aquest idioma no existeixen paquets en R que puguin ajudar-nos a obtenir la polaritat d’un Tweet.

Twitter s’ha convertit en una xarxa social molt important i d’un gran volum d’informació on l’anàlisi dels textos dels Tweets que s’escriuen pot oferir-nos una informació d’un gran valor. Obtenir la polaritat (positiu / negatiu) o els sentiments dels Tweets és una tasca complexa a causa de les característiques del llenguatge natural i de la pròpia forma d’un Tweet: un llenguatge dens de 280 caràcters com a màxim, que pot contenir abreviatures, paraules en argot, ironies , hashtags o mencions a altres usuaris entre altres elements. Totes aquestes característiques dificulten un correcte anàlisi i a causa d’això l’anàlisi de sentiment del llenguatge natural és un tema de molta actualitat.

En aquest anàlisi compararem diferents models per escollir aquell que ens ofereixi uns resultats de predicció millors, és a dir uns errors de classificació de Tweets positius menors. L’algoritme resultant d’aquesta comparativa s’emprarà en el panell de control desenvolupat i que formarà l’inspector sanitari d’aquest TFM.

2. Tractament de la Informació

En aquest apartat estudiarem la naturalesa de les dades a tractar per poder extreure les característiques que ens permetin crear els models predictius.

2.1. Anàlisi Descriptiu

El nostre conjunt de dades està format per un total de 11.290 Tweets que ja han estat categoritzats. Els nivells de classificació utilitzats són el següents:

  • Molt Positius (P+)
  • Positius (P)
  • Neutres (NEU)
  • Negatius (N)
  • Molt Negatius (N+)
  • Sense Clasificació (NONE)

Els fitxers emprats corresponen al taller TASS i, prèvia sol·licitud d’accés a la SEPLN, s’han obtingut de la següent adreça. TASS.

En concret els fitxers emprats són els següents:
- general-train-tagged
- intertass-train-tagged
- intertaas-development-tagged
- socialtv-train-tagged
- stompol-train-tagged

Són fitxers amb Tweets de diferents àmbits: general, vida social, política i categoritzats d’un manera subjectiva pel que podríem trobar Tweetss que per a una persona fossin positius i per a una altra negatius.

El primer pas a realitzar és fusionar tots els fitxers a tractar i seleccionar les columnes que ens interessen per poder realitzar els nostres models predictius. En concret ens interessa la columna “TEXT” i la columna “POLARITAT”. A continuació es pot veure l’estructura del DataFrame resultant.

Es pot veure també el Text de diversos Tweets i podem fixar-nos com ja podíem imaginar que el text pot tenir elements que són Hashtags (#), mencions a altres usuaris (@) o altres elements propis de Twitter com és la indicació per indicar que un Tweet és un ReTweet d’un altre (RT). Per centrar-nos només en el contingut propi del tuit i perquè aquests elements no puguin interferir en les prediccions dels nostres models eliminarem aquests elements. Aquest procés es realitzarà a posteriori, primer anem a analitzar els Tweets originals sense modificar.

## 'data.frame':    11290 obs. of  2 variables:
##  $ Texto    : chr  "Salgo de #VeoTV , que día más largoooooo..." "@PauladeLasHeras No te libraras de ayudar me/nos. Besos y gracias" "@marodriguezb Gracias MAR" "Off pensando en el regalito Sinde, la que se va de la SGAE cuando se van sus corruptos. Intento no sacar conclu"| __truncated__ ...
##  $ Polaridad: chr  "NONE" "NEU" "P" "N+" ...

La distribució dels Tweets segons la seva polaritat és la següent:

Per simplificar fusionarem Tweets “Molt Positius” i “Positius” i els “Molt Negatius” i “Negatius” per obtenir un total de 4 nivells de polaritat. La nova distribució és la següent. Podem veure com el nombre de Tweets “Positius” és lleugerament superior al nombre de Tweets “Negatius” el que ens indica una distrubición bastant equitativa.

Volem veure a continuació la distribució del contingut de les paraules que formen Tweets organitzat segons la polaritat del Tweet al qual pertanyen. Per això construirem el següent wordcloud.

Podem veure com el wordcloud ens il·lustra d’una manera gràfica com paraules com “gracias”, “feliz”, “bien” o “mejor” estan classificades en Tweets Positius i com a paraules com “violencia”, “mala”, “deficit” o “impuestos” estan classificades com a pertanyents a Tweets Negatius. Això ens indica que una predicció basada en el conjunt de paraules que formen un Tweet pot oferir bons resultats.

Ens fixem també, que ens trobem paraules que no ens apartaran valor per a la predicció com ara: “http”, números, o preposicions o articles. Com ja hem comentat dedicarem un apartat d’aquesta anàlisi a la neteja dels tuits per treballar només amb aquella informació que ens pugui aportar valor.

A continuació i atès que volem predir aquells tuits que siguin positius crearem la nostra variable dependent generant una nova variable factor d’aquells Tweets que siguin positius.

## 'data.frame':    11290 obs. of  3 variables:
##  $ Texto    : chr  "Salgo de #VeoTV , que día más largoooooo..." "@PauladeLasHeras No te libraras de ayudar me/nos. Besos y gracias" "@marodriguezb Gracias MAR" "Off pensando en el regalito Sinde, la que se va de la SGAE cuando se van sus corruptos. Intento no sacar conclu"| __truncated__ ...
##  $ Polaridad: Factor w/ 4 levels "N","NEU","NONE",..: 3 2 4 1 4 3 4 3 4 4 ...
##  $ Positivo : Factor w/ 2 levels "FALSE","TRUE": 1 1 2 1 2 1 2 1 2 2 ...

2.2 Training, Validació i Test

A continuació anem a dividir les nostres dades en Training, Validació i Test. Fem aquesta distribució per poder entrenar els nostres models en el conjunt de Training, validar-los en el conjunt de Validació i un cop seleccionat el millor model, obtenir el resultat final sobre el conjunt de test. La divisió que realitzarem del total dels tuits serà la següent:

  • Training (60%)
  • Validació (20%)
  • Test (20%)
## [1] 6775    3
## [1] 2258    3
## [1] 2257    3

2.3 Preparant el Corpus

En termes de processament de llenguatge, un Corpus és un conjunt gran i estructurat de textos. S’utilitzen per a realitzar anàlisis estadístics, verificar ocurrències o validar regles lingüístiques dins d’un àmbit lingüístic específic. En el nostre cas particular, estem parlant de la col·lecció de fragments de text que formen el conjunt de tots els Tweets.

Treballar amb un Corpus implica l’ús de tècniques de processament de llenguatge natural i com a tal l’extracció de característiques per determinar com influeixen les associacions de paraules en la polaritat d’un Tweet. Aquesta tasca pot esser complexa i segueix sent avui en dia un àmbit d’estudi molt actual.

En aquesta anàlisi i atès que l’objectiu és més aviat la comparació de models predictius que una extracció de característiques òptima utilitzarem el concepte de “Borsa de Paraules.” Els requisits d’un classificador de “Borsa de Paraules” “són mínims ja que només necessitem comptar les paraules, de manera que el procés es redueix a fer una certa simplificació i unificació dels termes i després contar-los.

Llavors, serà necessari processar els textos que formen els nostres Tweets per poder quedar-nos amb la informació que aporta valor al Tweet. Posteriorment crearem un corpus per poder extreure les freqüències de les paraules.

Per exemple, el contingut dels dos primers Tweets o documents es veu així.

## [1] "Salgo de #VeoTV , que día más largoooooo..."
## [1] "@PauladeLasHeras No te libraras de ayudar me/nos. Besos y gracias"

2.4. Neteja de dades

Per poder emprar el Corpus correctament necessitem simplificar i transformar el seu contingut a un format estàndard per a tots els Tweets. Els processos de neteja i estandardització que s’han realitzat han estat els següents:

  • Posar tot en minúscules.
  • Eliminar referències a URLs.
  • Eliminar Hashtags.
  • Eliminar indicadors de ReTweet.
  • Eliminar mencions a altres usuaris.
  • Eliminar nombres i espais en blanc.
  • Eliminar signes de puntuació
  • Eliminar stopwords a Espanyol que no ens proporcionen informació rellevant per a la nostra classificació (preposicions, articles, …)

Un cop realitzat aquest procés les dues primeres entrades es veuen així:

## [1] "salgo día largoooooo"
## [1] "no libraras ayudar menos besos gracias"

2.4 Feature Engineering

Per trobar les característiques del nostre classificador, posarem aquest Corpus a la forma d’una matriu de documents (DocumentTermMatrix). Una matriu de documents és una matriu numèrica que conté una columna per a cada paraula diferent en tot el nostre Corpus i una fila per a cada document. Una cel·la donada és igual a la freqüència en un document per a un terme donat.

D’aquesta manera fem servir les nostres entrades de text per construir freqüències de termes. Acabem amb les mateixes entrades en el nostre conjunt de dades però, en lloc de tenir-les definides per un text complet, ara estan definides per una sèrie de recomptes de les paraules més freqüents en tot el nostre corpus. Aquestes seran les característiques que utilitzarem per entrenar al nostre classificador.

## <<DocumentTermMatrix (documents: 9033, terms: 18528)>>
## Non-/sparse entries: 65034/167298390
## Sparsity           : 100%
## Maximal term length: 52
## Weighting          : term frequency (tf)

Un exemple de mostra de la nostra matriu és el següent:

## <<DocumentTermMatrix (documents: 50, terms: 10)>>
## Non-/sparse entries: 16/484
## Sparsity           : 97%
## Maximal term length: 12
## Weighting          : term frequency (tf)
## Sample             :
##     Terms
## Docs ayudar besos conclusiones día gracias largoooooo libraras mar menos
##   1       0     0            0   1       0          1        0   0     0
##   13      0     0            0   0       2          0        0   0     0
##   2       1     1            0   0       1          0        1   0     1
##   27      0     0            0   0       0          0        0   0     1
##   3       0     0            0   0       1          0        0   1     0
##   38      0     0            0   0       0          0        0   0     1
##   4       0     0            1   0       0          0        0   0     0
##   5       0     0            0   0       0          0        0   0     0
##   50      0     0            0   1       0          0        0   0     0
##   8       0     0            0   2       0          0        0   0     0
##     Terms
## Docs salgo
##   1      1
##   13     0
##   2      0
##   27     0
##   3      0
##   38     0
##   4      0
##   5      0
##   50     0
##   8      0

Atès que la matriu conté un total de 18.528 termes diferents i un valor de sparsity de 100% estudiarem les freqüències dels termes i només ens quedarem amb aquells més freqüents per descartar els menys freqüents i que no ens aporten valor. A continuació podem veure la distribució de freqüències de termes en la nostra matriu.

## (Intercept)           x 
##   8.1149688  -0.8591446

Com era d’esperar hi ha pocs termes amb una alta freqüència i molts termes amb freqüències baixes. Obtindrem a continuació una llista dels 20 termes més freqüents.

Per obtenir una representació més àmplia dels termes més freqüents generem a continuació un WordCloud on la mida i el color dels termes ens indica la quantitat d’aparicions en els textos.

Si l’objtetiu d’aquesta comparativa fos optimitzar l’extracció de característiques del llenguatge natural dels Tweets per poder optimitzar també el nostre classificador podríem continuar amb l’anàlisi de la informació i incorporar al model no només paraules independents unes de les altres (unigramas) sinó també de quina manera influeix la combinació de dues o més paraules en la predicció de la polaritat (bigrames, n-grams). Un exemple és la recerca d’associacions entre les paraules “madrid” o “gràcies”.

findAssocs(tdm, "madrid", 0.2)
## $madrid
##  real  hala ¡hala 
##  0.47  0.42  0.21
findAssocs(tdm, "gracias", 0.2)
## $gracias
## muchas 
##   0.21

Incorporant aquesta informació al nostre model podríem optimitzar les prediccions dels nostres algoritmes ja que consideraríem combinacions de paraules en lloc de només paraules independents. Atès que no es tracta de l’objectiu d’aquesta comparativa ens centrarem en la generació dels models predictius per paraules independents.

Atès que alguns termes són més importants que d’altres, volem eliminar aquells que no ho són tant. Podem fer servir per això la funció removeSparseTerms del paquet “tm” on indicam la matriu i un nombre que proporciona la dispersió màxima permesa per a un terme en el nostre corpus.

Per exemple, si volem termes que apareguin en almenys l’1% dels documents, podem fer el següent.

Acabem amb només 1117 termes.

Ara volem convertir aquesta matriu en dos DataFrames diferents, un training i un altre de validació que puguem utilitzar per entrenar i validar els nostres models.

D’aquesta manera obtenim un DataFrame per als nostres valors d’entrenament format per 6775 mostres i 1118 columnes. 1117 variables independents i una variable dependent.

## [1] 6775 1117

De la mateixa manera pel nostre conjunt de validació.

## [1] 2258 1117

3. Models de Clasificació

En aquest apartat estudiarem i compararem els diferents models de classificació que ens permetran obtenir prediccions sobre la polaritat d’un Tweet concret. Per poder comparar-los ens basarem en l’error de classificació que haurem obtingut després d’entrenar els nostres models en el conjunt de dades de Training i realitzar les prediccions en el conjunt de dades de Validació realitzant Validació Creuada per a aquells models que necessiten ajustar alguns paràmetres. Guardarem el valor obtingut per a cada un dels models i finalment els comparem per realitzar les prediccions en les dades de test.

3.1. Error Mínim de Clasificació

Segons la naturalesa de les dades podria succeir que alhora d’intentar predir Tweets positius, la gran majoria dels nostres Tweets ja fossin classificats com a positius fet que faria que el nostre classificador no fos realista. Hem vist com la proporció entre Tweets positius i negatius era més o menys equitativa però tot i així necessitem saber l’error mínim de classificació per saber a partir de quines prediccions de classificació dels nostres models s’obtenen millors valors que el simple fet d’obtenir-los a l’atzar.

A continuació obtindrem l’error mínim de classificació per sobre del qual en aplicar els algoritmes d’aquesta comparativa podrem dir que obtenim una millor classificació que simplement generar un valor aleatori.

## 
## FALSE  TRUE 
##  6996  4294
##     FALSE 
## 0.6196634

3.2. Regresió Logística

L’algoritme de classificació de regressió logística ens permet predir la probabilitat d’una variable dependent categòrica sent el resultat una variable binària que conté valors de 0 o 1. Atès que volem predir si un Tweet serà positiu o no (2 classes) pot ser que aquest mètode ens ofereixi bons resultats. Esperem que en el nostre cas també pugui explicar la relació entre la variable dependent i les variables independents.



## 
## Call:
## glm(formula = Positivo ~ ., family = "binomial", data = train_data_words_df)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -2.4641  -0.8861  -0.7730   1.1826   2.2068  
## 
## Coefficients:
##               Estimate Std. Error z value Pr(>|z|)    
## (Intercept) -0.7323783  0.0366607 -19.977  < 2e-16 ***
## día          0.4605397  0.1653209   2.786 0.005341 ** 
## gracias      2.3058155  0.1910087  12.072  < 2e-16 ***
## menos        0.0694611  0.2145064   0.324 0.746075    
## hoy          0.2596312  0.1217492   2.133 0.032965 *  
## madrid       0.7408895  0.1222590   6.060 1.36e-09 ***
## grande       1.7651917  0.2935412   6.013 1.82e-09 ***
## ser          0.2671174  0.1851876   1.442 0.149185    
## congreso     0.1258858  0.2400809   0.524 0.600037    
## días        -0.0670074  0.2364503  -0.283 0.776879    
## gran         1.1292641  0.1987087   5.683 1.32e-08 ***
## ahora       -0.3084953  0.1638956  -1.882 0.059800 .  
## mundo        0.0830176  0.2840656   0.292 0.770097    
## sin         -0.6122986  0.1871093  -3.272 0.001066 ** 
## puede       -0.4800905  0.2503317  -1.918 0.055134 .  
## siempre      0.6988010  0.2290179   3.051 0.002279 ** 
## copa         0.0827461  0.2053607   0.403 0.686999    
## españa      -0.0718947  0.1823331  -0.394 0.693357    
## ver          0.2994785  0.1764110   1.698 0.089580 .  
## noche        0.1393706  0.2284307   0.610 0.541781    
## dos         -0.0005818  0.2281710  -0.003 0.997966    
## hace        -0.2542465  0.2151294  -1.182 0.237273    
## así          0.0728419  0.2227494   0.327 0.743658    
## nuevo        0.7814632  0.2398250   3.258 0.001120 ** 
## vía         -0.0081445  0.2050206  -0.040 0.968312    
## años         0.2194617  0.2247444   0.976 0.328820    
## nada        -0.1975717  0.2150998  -0.919 0.358351    
## vez         -0.3147683  0.2542632  -1.238 0.215730    
## bien         0.9488766  0.1910591   4.966 6.82e-07 ***
## bueno        0.7987374  0.2058748   3.880 0.000105 ***
## tan         -0.3227490  0.2449885  -1.317 0.187703    
## buenos       0.8927860  0.2706529   3.299 0.000972 ***
## gobierno    -0.0620990  0.1747777  -0.355 0.722363    
## solo        -0.1794140  0.2228681  -0.805 0.420806    
## rajoy       -0.3966623  0.1754378  -2.261 0.023760 *  
## final       -0.3151125  0.2555826  -1.233 0.217606    
## mas          0.4686867  0.1689887   2.773 0.005546 ** 
## mejor        1.3828335  0.1886274   7.331 2.28e-13 ***
## rey          0.3128600  0.2423094   1.291 0.196649    
## vamos        0.8559184  0.2088448   4.098 4.16e-05 ***
## equipo       1.1773687  0.2810960   4.188 2.81e-05 ***
## partido      0.2821810  0.1995863   1.414 0.157412    
## año          0.3359430  0.2100643   1.599 0.109767    
## pues        -0.2130868  0.2508325  -0.850 0.395593    
## cosas       -0.5001837  0.2941208  -1.701 0.089017 .  
## feliz        1.9344542  0.3504378   5.520 3.39e-08 ***
## barcelona   -1.0691233  0.2576430  -4.150 3.33e-05 ***
## real        -0.0434429  0.1890871  -0.230 0.818285    
## barça       -0.5495611  0.2107012  -2.608 0.009101 ** 
## rubalcaba    0.0134573  0.2593373   0.052 0.958616    
## aquí         0.5461401  0.2242121   2.436 0.014858 *  
## psoe        -0.6724988  0.2415979  -2.784 0.005377 ** 
## mañana       0.2087931  0.1707710   1.223 0.221462    
## dice        -0.7798370  0.2531734  -3.080 0.002068 ** 
## hacer       -0.1686270  0.2201327  -0.766 0.443662    
## portada     -1.5342718  0.3597881  -4.264 2.00e-05 ***
## contra      -0.6159529  0.2794023  -2.205 0.027487 *  
## messi       -1.0080507  0.2352887  -4.284 1.83e-05 ***
## ramos       -0.9139156  0.2822291  -3.238 0.001203 ** 
## bale         0.7692322  0.1847618   4.163 3.14e-05 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 9000.5  on 6774  degrees of freedom
## Residual deviance: 8116.0  on 6715  degrees of freedom
## AIC: 8236
## 
## Number of Fisher Scoring iterations: 4

La funció de summary ens dona una visió realment bona del model que acabem de construir. La secció de coeficients enumera totes les variables d’entrada utilitzades en el model.

Els arteriscs ens ofereixen la importància de cadascuna de les variables en termes estadístics. Així per exemple tenim que el terme “gracias” té un alt nivell significatiu i un valor positiu a la columna “Estimate”. Pel que és molt probable que un Tweet amb aquesta paraula sigui classificat com a positiu.

Ara utilitzarem el model per a una predicció en les dades de Validació. Utilitzarem type = “response” perquè els resultats de la predicció siguin probabilitats i el llindar de 0.5 per classificar la resposta com com a negativa (<0.5) o positiva (> 0.5).

## [1] 0.6961913

Veiem que amb el model de regressió logística obtenim una precisió bastant millor que l’obtinguda pel model base.

Ara per comprovar les prediccions realitzades sobre Tweets utilitzats farem servir el nostre model per etiquetar els Tweets i després obtenir una mostra aleatòria de 5 Tweets classificats com a positius.

## [1] "Vamos a por el viernes (@ Ayuntamiento de Málaga) [pic]: http://t.co/lzDVsoCu"                                                   
## [2] "Ya esta aquí. Ya llegó por fin la quinta ensaladera. Gracias a todos los miembros del equipo hoy mucha gente dormirá feliz."     
## [3] "Una lástima lo de hoy pero esto no termina acá. En el fútbol siempre hay revancha y tenemos equipo para pelear por grandes cosas"
## [4] "Gracias ;) RT @sanzchile: *7714 México ;) RT: @AlejandroSanz: Voten por @Oscarcruzvm hay que (cont) http://t.co/pCXYPmr5"        
## [5] "De nuevo Ai Weiwei luchando por la democracia en China http://t.co/VzDM6QYg"

A continuació una mostra aleatòria de 5 Tweets classificats com a negatius:

## [1] "Open Master Class@javiersolana &Pedro Alonso on \"Global Health Challenges&Global Governance\"@esadegeo@ISGLOBALorg http://t.co/UzhGWbiB… ." 
## [2] "El desempleo en EE UU baja a los niveles de marzo de 2009 http://t.co/2RKKqQFG"                                                              
## [3] "@SSantiagosegura @angyfdz @flofdez BORRADO ESTÁ AMIGUETES!! UN ABRUZO!!;)"                                                                   
## [4] "RT@FranHervias:UPyD pacta con Cascos para tener grupo.A pesar d que en 2008 decían que no era lícito este tipo d pactos http://t.co/fG5cVwM9"
## [5] "Palmas por sevillanas para animar a Rafa!! #sevillaciudadtalisman #copadavis"

– Efecte Marginal

Calculem ara els coeficients de la regressió logística, és a dir els efectes marginals, per saber la influència de cada variable independent en el resultat de la variable dependent. És a dir, com canvien les probabilitats que un Tweet sigui positiu a causa del canvi d’una unitat en les variables independents.

Quan els models impliquen una transformació no lineal, els coeficients generalment no són interpretables directament. Això es deu al fet que els coeficients expressen la influència de cada variable separada sobre la variable dependent en l’escala lineal del resultat, no l’escala discreta (o probabilitat) del resultat. Per exemple, en una regressió logística, els coeficients expressen l’efecte marginal de cada variable inclosa en termes del canvi en les probabilitats que l’esdeveniment sigui igual a 1 donat el canvi d’una unitat en la variable independent.

Per tal d’expressar el canvi d’una manera més intuïtiva en la probabilitat predita que el resultat és igual a 1, es requereix condicionar totes les altres variables incloses (és a dir, seleccionar un conjunt de valors per a totes les variables independents) i executar aquest conjunt de valors a través de la funció de logit per convertir els valors en probabilitats fent així que l’efecte marginal (en termes de probabilitat) d’una variable sigui una funció de totes les altres variables incloses en el model.

En realitat l’efecte marginal d’una variable donada és la pendent de la superfície de regressió respecte a una altra variable i ens indica la velocitat a la qual la variable dependent canvia en un punt donat, amb respecte a una dimensió concreta i mantenint constants tots els valors de les variables.

És un valor particularment útil perquè és intuïtiu, és simplement una pendent, i perquè pot ser calculat a partir d’essencialment qualsevol conjunt d’estimacions de regressió.

##     factor     AME     SE       z      p   lower   upper
##      ahora -0.0636 0.0338 -1.8839 0.0596 -0.1298  0.0026
##        año  0.0693 0.0433  1.6003 0.1095 -0.0156  0.1541
##       años  0.0452 0.0463  0.9767 0.3287 -0.0455  0.1360
##       aquí  0.1126 0.0462  2.4397 0.0147  0.0221  0.2031
##        así  0.0150 0.0459  0.3270 0.7437 -0.0750  0.1050
##       bale  0.1586 0.0379  4.1831 0.0000  0.0843  0.2329
##      barça -0.1133 0.0434 -2.6126 0.0090 -0.1983 -0.0283
##  barcelona -0.2204 0.0529 -4.1662 0.0000 -0.3241 -0.1167
##       bien  0.1956 0.0391  5.0002 0.0000  0.1190  0.2723
##      bueno  0.1647 0.0423  3.8963 0.0001  0.0818  0.2475
##     buenos  0.1841 0.0556  3.3088 0.0009  0.0750  0.2931
##   congreso  0.0260 0.0495  0.5244 0.6000 -0.0711  0.1230
##     contra -0.1270 0.0575 -2.2070 0.0273 -0.2398 -0.0142
##       copa  0.0171 0.0423  0.4030 0.6870 -0.0659  0.1000
##      cosas -0.1031 0.0606 -1.7018 0.0888 -0.2219  0.0156
##        día  0.0950 0.0340  2.7917 0.0052  0.0283  0.1616
##       días -0.0138 0.0487 -0.2834 0.7769 -0.1094  0.0817
##       dice -0.1608 0.0521 -3.0864 0.0020 -0.2629 -0.0587
##        dos -0.0001 0.0470 -0.0025 0.9980 -0.0923  0.0921
##     equipo  0.2427 0.0577  4.2079 0.0000  0.1297  0.3558
##     españa -0.0148 0.0376 -0.3943 0.6933 -0.0885  0.0589
##      feliz  0.3988 0.0717  5.5621 0.0000  0.2583  0.5394
##      final -0.0650 0.0527 -1.2334 0.2174 -0.1682  0.0383
##   gobierno -0.0128 0.0360 -0.3553 0.7224 -0.0834  0.0578
##    gracias  0.4754 0.0380 12.5251 0.0000  0.4010  0.5498
##       gran  0.2328 0.0406  5.7341 0.0000  0.1532  0.3124
##     grande  0.3639 0.0600  6.0703 0.0000  0.2464  0.4815
##       hace -0.0524 0.0443 -1.1822 0.2371 -0.1393  0.0345
##      hacer -0.0348 0.0454 -0.7661 0.4436 -0.1237  0.0542
##        hoy  0.0535 0.0251  2.1351 0.0328  0.0044  0.1027
##     madrid  0.1528 0.0250  6.1207 0.0000  0.1038  0.2017
##     mañana  0.0430 0.0352  1.2231 0.2213 -0.0259  0.1120
##        mas  0.0966 0.0348  2.7792 0.0055  0.0285  0.1648
##      mejor  0.2851 0.0383  7.4386 0.0000  0.2100  0.3602
##      menos  0.0143 0.0442  0.3238 0.7461 -0.0724  0.1010
##      messi -0.2078 0.0483 -4.3021 0.0000 -0.3025 -0.1132
##      mundo  0.0171 0.0586  0.2923 0.7701 -0.0977  0.1319
##       nada -0.0407 0.0443 -0.9187 0.3582 -0.1276  0.0462
##      noche  0.0287 0.0471  0.6102 0.5417 -0.0636  0.1210
##      nuevo  0.1611 0.0493  3.2682 0.0011  0.0645  0.2577
##    partido  0.0582 0.0411  1.4146 0.1572 -0.0224  0.1388
##    portada -0.3163 0.0739 -4.2789 0.0000 -0.4612 -0.1714
##       psoe -0.1387 0.0497 -2.7884 0.0053 -0.2361 -0.0412
##      puede -0.0990 0.0516 -1.9196 0.0549 -0.2000  0.0021
##       pues -0.0439 0.0517 -0.8497 0.3955 -0.1453  0.0574
##      rajoy -0.0818 0.0361 -2.2637 0.0236 -0.1526 -0.0110
##      ramos -0.1884 0.0580 -3.2460 0.0012 -0.3022 -0.0747
##       real -0.0090 0.0390 -0.2298 0.8183 -0.0854  0.0675
##        rey  0.0645 0.0499  1.2917 0.1965 -0.0334  0.1624
##  rubalcaba  0.0028 0.0535  0.0519 0.9586 -0.1020  0.1076
##        ser  0.0551 0.0382  1.4432 0.1490 -0.0197  0.1299
##    siempre  0.1441 0.0471  3.0586 0.0022  0.0518  0.2364
##        sin -0.1262 0.0385 -3.2804 0.0010 -0.2017 -0.0508
##       solo -0.0370 0.0459 -0.8052 0.4207 -0.1270  0.0531
##        tan -0.0665 0.0505 -1.3180 0.1875 -0.1655  0.0324
##      vamos  0.1765 0.0429  4.1179 0.0000  0.0925  0.2605
##        ver  0.0617 0.0363  1.6989 0.0893 -0.0095  0.1330
##        vez -0.0649 0.0524 -1.2384 0.2156 -0.1676  0.0378
##        vía -0.0017 0.0423 -0.0397 0.9683 -0.0845  0.0812

Podem comprovar com paraules com “gracias”, “grande” o “mejor” tenen un efecte marginal mitjana (AME) gran pel que la seva presència influeix en què un Tweet sigui classificat com Positiu. En canvi paraules com “contra” o “sin” influeixen en què un Tweet sigui classificat com no Positiu.

A continuació il·lustrarem com influeix la combinació de les paraules “gracias” i “grande” en la predicció d’un Tweet Positiu:

## 
## # Predicted probabilities of Positivo 
## # x = gracias 
## 
## # 0
##  x predicted std.error conf.low conf.high
##  0     0.352     0.028    0.340     0.365
##  1     0.845     0.189    0.790     0.888
##  2     0.982     0.379    0.963     0.991
##  3     0.998     0.570    0.994     0.999
## 
## # 1
##  x predicted std.error conf.low conf.high
##  0     0.761     0.292    0.642     0.849
##  1     0.970     0.348    0.942     0.984
##  2     0.997     0.480    0.992     0.999
##  3     1.000     0.642    0.999     1.000
## 
## # 2
##  x predicted std.error conf.low conf.high
##  0     0.949     0.585    0.855     0.983
##  1     0.995     0.616    0.982     0.998
##  2     0.999     0.699    0.998     1.000
##  3     1.000     0.820    1.000     1.000
## 
## Adjusted for:
## *      día = 0.02
## *     menos = 0.02
## *       hoy = 0.05
## *    madrid = 0.06
## *       ser = 0.02
## *  congreso = 0.01
## *     días = 0.02
## *      gran = 0.02
## *     ahora = 0.03
## *     mundo = 0.01
## *       sin = 0.03
## *     puede = 0.01
## *   siempre = 0.01
## *      copa = 0.03
## *   españa = 0.02
## *       ver = 0.02
## *     noche = 0.01
## *       dos = 0.01
## *      hace = 0.02
## *      así = 0.01
## *     nuevo = 0.01
## *      vía = 0.02
## *     años = 0.01
## *      nada = 0.02
## *       vez = 0.01
## *      bien = 0.02
## *     bueno = 0.01
## *       tan = 0.01
## *    buenos = 0.02
## *  gobierno = 0.02
## *      solo = 0.02
## *     rajoy = 0.03
## *     final = 0.01
## *       mas = 0.02
## *     mejor = 0.02
## *       rey = 0.02
## *     vamos = 0.01
## *    equipo = 0.01
## *   partido = 0.02
## *      año = 0.01
## *      pues = 0.01
## *     cosas = 0.01
## *     feliz = 0.01
## * barcelona = 0.02
## *      real = 0.02
## *    barça = 0.02
## * rubalcaba = 0.01
## *     aquí = 0.01
## *      psoe = 0.02
## *   mañana = 0.02
## *      dice = 0.02
## *     hacer = 0.02
## *   portada = 0.01
## *    contra = 0.01
## *     messi = 0.02
## *     ramos = 0.02
## *      bale = 0.02

I com influeix la combinació de les paraules “contra” i “sense” en la predicció d’un Tweet Negatiu:

## 
## # Predicted probabilities of Positivo 
## # x = contra 
## 
## # 0
##  x predicted std.error conf.low conf.high
##  0     0.384     0.028    0.371     0.397
##  1     0.252     0.278    0.163     0.367
##  2     0.154     0.557    0.057     0.351
## 
## # 1
##  x predicted std.error conf.low conf.high
##  0     0.252     0.186    0.190     0.327
##  1     0.154     0.333    0.087     0.259
##  2     0.090     0.586    0.030     0.237
## 
## # 2
##  x predicted std.error conf.low conf.high
##  0     0.155     0.372    0.081     0.275
##  1     0.090     0.463    0.038     0.197
##  2     0.051     0.668    0.014     0.165
## 
## # 3
##  x predicted std.error conf.low conf.high
##  0     0.090     0.558    0.032     0.229
##  1     0.051     0.623    0.016     0.154
##  2     0.028     0.787    0.006     0.119
## 
## # 4
##  x predicted std.error conf.low conf.high
##  0     0.051     0.745    0.012     0.188
##  1     0.028     0.794    0.006     0.121
##  2     0.015     0.929    0.003     0.088
## 
## Adjusted for:
## *      día = 0.02
## *   gracias = 0.04
## *     menos = 0.02
## *       hoy = 0.05
## *    madrid = 0.06
## *    grande = 0.01
## *       ser = 0.02
## *  congreso = 0.01
## *     días = 0.02
## *      gran = 0.02
## *     ahora = 0.03
## *     mundo = 0.01
## *     puede = 0.01
## *   siempre = 0.01
## *      copa = 0.03
## *   españa = 0.02
## *       ver = 0.02
## *     noche = 0.01
## *       dos = 0.01
## *      hace = 0.02
## *      así = 0.01
## *     nuevo = 0.01
## *      vía = 0.02
## *     años = 0.01
## *      nada = 0.02
## *       vez = 0.01
## *      bien = 0.02
## *     bueno = 0.01
## *       tan = 0.01
## *    buenos = 0.02
## *  gobierno = 0.02
## *      solo = 0.02
## *     rajoy = 0.03
## *     final = 0.01
## *       mas = 0.02
## *     mejor = 0.02
## *       rey = 0.02
## *     vamos = 0.01
## *    equipo = 0.01
## *   partido = 0.02
## *      año = 0.01
## *      pues = 0.01
## *     cosas = 0.01
## *     feliz = 0.01
## * barcelona = 0.02
## *      real = 0.02
## *    barça = 0.02
## * rubalcaba = 0.01
## *     aquí = 0.01
## *      psoe = 0.02
## *   mañana = 0.02
## *      dice = 0.02
## *     hacer = 0.02
## *   portada = 0.01
## *     messi = 0.02
## *     ramos = 0.02
## *      bale = 0.02



3.3 Linear Discriminant Analysis (LDA)

A partir del teorema de Bayes, LDA estima la probabilitat que una observació, donat un determinat valor de les variables independents, pertanyi a una de les classes de la variable qualitativa, P (I = k | X = x). Un cop obtinguda la proabilidad i per realitzar la classificació s’assigna l’observació a la classe k per la qual la probabilitat predita és més gran.

##                    LD1
## día        0.664754446
## gracias    2.544478910
## menos      0.113407694
## hoy        0.354617911
## madrid     1.013783726
## grande     2.050711967
## ser        0.343875310
## congreso   0.145191385
## días      -0.072714288
## gran       1.488400037
## ahora     -0.397779584
## mundo      0.059939255
## sin       -0.694346379
## puede     -0.635106813
## siempre    0.821424622
## copa       0.115818662
## españa    -0.111321212
## ver        0.387978812
## noche      0.133854015
## dos        0.016689710
## hace      -0.335136426
## así        0.116561580
## nuevo      1.051328491
## vía       -0.035899615
## años       0.293411185
## nada      -0.261282957
## vez       -0.395191127
## bien       1.279603619
## bueno      1.145744815
## tan       -0.452328720
## buenos     1.271221719
## gobierno  -0.094866588
## solo      -0.243929587
## rajoy     -0.505452937
## final     -0.373058993
## mas        0.636680255
## mejor      1.782001497
## rey        0.419783065
## vamos      1.214818149
## equipo     1.430379004
## partido    0.397574893
## año        0.377025232
## pues      -0.266543074
## cosas     -0.623905905
## feliz      2.280061300
## barcelona -1.207934129
## real      -0.071301920
## barça     -0.657438290
## rubalcaba -0.001741248
## aquí       0.709184599
## psoe      -0.809361474
## mañana     0.287791652
## dice      -0.883922833
## hacer     -0.225172413
## portada   -1.571297628
## contra    -0.761582348
## messi     -1.113180589
## ramos     -1.094742067
## bale       0.715900476

Quan representam els coeficients de la funció discriminant lineal veiem hi ha una zona que es solapa. Aquesta és la zona que incrementarà el valor de les taxes d’error de classificació del model.

La predicció que s’obté sobre el conjunt de validació és la següent:

## [1] 0.7015058

Veiem com és lleugerament superior a l’obtinguda per Logit.

3.4. Quadratic Discriminant Analysis (QDA)

L’anàlisi disciminante quadràtic considera que cada classe k té la seva pròpia matriu de covariança i, com a conseqüència, la funció discriminant pren forma quadràtica. A causa d’això genera límits de decisió corbs pel que pot aplicar-se a situacions en què la separació entre grups no és lineal.

## Call:
## qda(Positivo ~ ., data = train_data_words_df)
## 
## Prior probabilities of groups:
##    FALSE     TRUE 
## 0.619631 0.380369 
## 
## Group means:
##              día     gracias      menos        hoy     madrid      grande
## FALSE 0.01715102 0.007860886 0.01595998 0.04311577 0.04097189 0.003811339
## TRUE  0.03337214 0.091191308 0.01435778 0.05781917 0.08963912 0.025611176
##              ser   congreso       días        gran      ahora       mundo
## FALSE 0.01858028 0.01333969 0.01667461 0.009528347 0.03358742 0.008575512
## TRUE  0.02483508 0.01125340 0.02444703 0.032984090 0.02367094 0.015133877
##              sin      puede     siempre       copa     españa        ver
## FALSE 0.03096713 0.01476894 0.009051929 0.03454026 0.02310624 0.02024774
## TRUE  0.01590997 0.01008925 0.023670935 0.03531238 0.02017850 0.02522313
##            noche        dos       hace        así       nuevo        vía
## FALSE 0.01071939 0.01310148 0.01715102 0.01191043 0.008099095 0.01786565
## TRUE  0.01668607 0.01164144 0.01552192 0.01590997 0.018238262 0.01513388
##             años       nada         vez       bien      bueno        tan
## FALSE 0.01333969 0.01762744 0.013816103 0.01167222 0.01000476 0.01262506
## TRUE  0.01435778 0.01396973 0.009313155 0.03065580 0.02289484 0.01280559
##           buenos   gobierno       solo      rajoy      final        mas
## FALSE 0.01000476 0.02596475 0.01595998 0.03358742 0.01214864 0.01810386
## TRUE  0.02405898 0.02017850 0.01396973 0.01862631 0.01047730 0.03065580
##            mejor        rey      vamos      equipo    partido        año
## FALSE 0.01048118 0.01643640 0.01024297 0.005002382 0.01405431 0.01238685
## TRUE  0.04850601 0.02483508 0.02173069 0.021342646 0.01862631 0.01785021
##             pues       cosas       feliz   barcelona       real      barça
## FALSE 0.01262506 0.011195808 0.002382087 0.019056694 0.01572177 0.01977132
## TRUE  0.01086535 0.007372914 0.023670935 0.008925107 0.03531238 0.01474583
##         rubalcaba       aquí        psoe     mañana        dice      hacer
## FALSE 0.012625060 0.01071939 0.020962363 0.02024774 0.021676989 0.01667461
## TRUE  0.008925107 0.01862631 0.009313155 0.02483508 0.007760962 0.01280559
##           portada      contra       messi       ramos       bale
## FALSE 0.017389233 0.014530729 0.024535493 0.019771320 0.01214864
## TRUE  0.003492433 0.006596818 0.009313155 0.008925107 0.03531238

El valor de predicció de QDA en el conjunt de validació és el següent:

## [1] 0.6607617

Veiem que el valor obtingut és inferior a l’obtingut en models anteriors.

3.5. Arbres de Clasificació

En el model dels arbres de classificació a cada pas s’avaluen totes les variables d’entrada i tots els punts de divisió possibles i es tria la que tingui millor resultat. És a dir, dividim les dades en dos o més conjunts homogenis basats en la variable més significativa.

És molt probable que aquest model no funcioni correctament per les nostres dades ja que els models basats en arbres no estan dissenyats per funcionar amb característiques molt disperses i tal com hem pogut veure en l’apartat d’anàlisi d’informació, les nostres dades tenen valors de sparsity molt elevats.

Si entrenem un model amb el model d’arbres de decisió veiem com només ens dectecta 2 nodes terminals sent el terme “gràcias” determinant per predir si un Tweet és Positiu o no. És un indicador que la variable “gracies” classifica gairebé perfectament a les nostres mostres i encara que sembla correcte, a causa de la limitació d’aquest model i a la naturalesa de les nostres dades, això no ens permet contemplar altres possibilitats de combinacions de termes, de manera que no podria servir-nos per exemple per classificar un Tweet que no tingui la paraula “gracias” ja que sempre obtindríem com a resultat que el Tweet és negatiu.

Per realitzar la predicció, el model recorre l’arbre en funció del valor de les seves variables fins a arribar a un dels nodes terminals. En el cas de classificació, sol emprar-se la classe més freqüent del node per decidir quina variable escollir.

## [1] 0.6466421

Per comprovar si es genera overfitting, farem una predicció sobre el conjunt de dades d’entrenament. Veiem com el resultat obtingut no és molt alt. Fet que ens indica que el model no genera overfitting sobre les dades d’Training. Fem ara la predicció sobre les dades de Validació.

## [1] 0.6390611

Efectivament, obtenim un valor molt semblant a l’obtingut amb les dades de Training (No overfitting) però és dels més baixos obtinguts fins ara amb tots els models aplicats. La limitació d’aquest model és que només es genera un únic arbre i per tant només és capaç de comprovar una combinació de probabilitats que en el nostre cas resulta ser molt limitada.

– Controlar el tamany de l’arbre

Hem comprovat com el model no genera overfitting i com per tant, no és necessari realitzar cap tipus de limitació de la mida de l’arbre o poda, però volem generar un model que pugui servir-nos per a altres conjunts de dades als utilitzats en aquesta comparativa pel que realitzarem els procediments habituals per obtenir els paràmetres més òptims d’aquest model.

La mida final pot controlar-se mitjançant regles per la divisió dels nodes depenent de si es compleixen o no determinades condicions. Són les següents:

  • Observacions mínimes per divisió: defineix el nombre mínim d’observacions que ha de tenir un node per poder ser dividit. Com més gran el valor, menys flexible és el model.

  • Observacions mínimes de node terminal: defineix el nombre mínim d’observacions que han de tenir els nodes terminals. El seu efecte és molt similar al d’observacions mínimes per divisió.

  • Profunditat màxima de l’arbre: defineix la profunditat màxima de l’arbre, entenent per profunditat màxima el nombre de divisions de la branca més llarga (en sentit descendent) de l’arbre.

  • Nombre màxim de nodes terminals: defineix el nombre màxim de nodes terminals que pot tenir l’arbre. Un cop assolit el límit, s’aturen les divisions. El seu efecte és similar al de controlar la profunditat màxima de l’arbre.

  • Reducció mínima d’error: defineix la reducció mínima d’error que ha d’aconseguir una divisió perquè es dugui a terme.

Tots aquests paràmetres són el que es coneix com hiperparàmetres perquè no s’aprenen durant l’entrenament del model. El seu valor ha de ser especificat per l’usuari en base al seu coneixement del problema i mitjançant l’ús de validació creuada.

Tot i que no tingui sentit per al nostre cas, vam realitzar Validació Creuada per podar i obtenir la mida de l’arbre amb menor error de classificació

## $size
## [1] 2 1
## 
## $dev
## [1] 2382 2577
## 
## $k
## [1] -Inf  183
## 
## $method
## [1] "misclass"
## 
## attr(,"class")
## [1] "prune"         "tree.sequence"
## [1] 2

Efectivament l’arbre amb menor error de classificació té dos nodes terminals.

Realitzem el procés de Poda indicant el paràmetre best obtingut a la funció prune.misclass

I òbviament obtenim el mateix arbre.

Veurem a continuació com afecta el procés de poda als valors de predicció sobre Training i Validació per comprovar l’overfitting. (En el nostre cas no variaran dels valors obtinguts anteriorment.)

Per a Training:

## [1] 0.6466421

Per a Validació:

## [1] 0.6390611

Veiem com obtenim els mateixos valors que els obtinguts anteriorment però la realització del procés complet ens permet canviar el nostre conjunt de dades original i disposar de tota la lògica necessària per analitzar aquest model completament.

3.6. Bagging

El model dels arbres de classificació pateix també el problema de l’equilibri entre biaix i variànça. Per solucionar-ho i trobar el millor equilibri utilitzarem els models de Bagging i Boosting.

A Bagging en lloc de crear un model d’un únic arbre s’ajusten molts models amb diferents mostres (obtingudes a través d ’ Bootstrapping ) de manera paral·lela formant un “bosc” de tal manera que tots els arbres participen en la realització d’una predicció i com a valor final es té en compte la classe més freqüent. D’aquesta manera es fan servir models amb poc biaix però molta variànça, però afegint molts d’aquests models s’aconsegueix reduir la variànça.

A Bagging la forma d’obtenir les mostres a través de Bootstrapping permet que es pugui estimar l’error directament a través del “Out Of Bag” (OOB) format per una mitjana d’un terç de les mostres emprades. Aquest terç que Bootstrapping no ha utilitzat per a la selecció d’observacions pot utilitzar-se per realitzar la predicció i en el nostre cas obtenir el “OOB-classification-error”.

A continuació entrenem el model de Bagging amb les nostres dades de Training.

## 
## Call:
##  randomForest(formula = Positivo ~ ., data = train_data_words_df) 
##                Type of random forest: classification
##                      Number of trees: 500
## No. of variables tried at each split: 7
## 
##         OOB estimate of  error rate: 32.19%
## Confusion matrix:
##       FALSE TRUE class.error
## FALSE  3766  432   0.1029061
## TRUE   1749  828   0.6786962

Anem a comprovar si hi ha “overfitting”. Per això realitzarem la predicció sobre les dades d’Training.

## [1] 0.7138007

Comprovam com la precisió en el model de classificació és molt alta, pel que es tracta d’un indicador d’“overfitting”.

Fem ara la predicció en el conjunt de Validació.

## [1] 0.6913198

Veiem com amb el model de Bagging obtenim una bona precisió de classificació. La guardem per poder comparar-la amb tots els models.

3.7. Random Forest

Es tracta d’un dels mètodes de Bagging més coneguts. Té en compte la correlació que hi pot haver entre els múltiples arbres generats ja que si la correlació entre ells és alta no es podrà aconseguir reduir la variança d’una manera notable. Per solucionar aquest problema Random Forest realitza una selecció aleatòria de m predictors abans d’avaluar cada divisió dels arbres per evitar que els predictors influents puguin ser seleccionats i així que la correlació entre els arbres generats sigui alta.

Tant Bagging com Random Forest segueixen les mateixes passes però Random Forest realitza un pas addicional de selecció de predictors abans de cada divisió. Es pot dir que Bagging és una generalització de Random Forest per m = p. Aquest fet ens indica que haurem de triar un m òptim.

Vegem a continuació l’evolució del OOB-Error en funció del paràmetre m per escollir l’òptim. També realitzarem una gràfica comparativa entre el Test-Error i el OOB-Error.

## # A tibble: 1 x 2
##   n_predictores oob_err_rate
##           <int>        <dbl>
## 1             6        0.327

Obtenim que 6 és el nombre de predictors òptim a utilitzar. Farem servir aquest valor per optimitzar la mida dels nodes terminals.

## # A tibble: 20 x 2
##     size oob_err_rate
##    <int>        <dbl>
##  1    18        0.320
##  2    16        0.321
##  3    11        0.321
##  4     6        0.321
##  5     7        0.321
##  6     9        0.321
##  7    20        0.321
##  8    17        0.321
##  9    13        0.321
## 10    10        0.322
## 11    12        0.322
## 12     3        0.322
## 13    19        0.322
## 14     2        0.323
## 15    14        0.323
## 16     1        0.323
## 17    15        0.324
## 18     8        0.324
## 19     4        0.325
## 20     5        0.325

## # A tibble: 1 x 2
##    size oob_err_rate
##   <int>        <dbl>
## 1    18        0.320

Obtenim que el nombre òptim d’observacions mínimes dels nodes terminals és 18.

Un cop obtinguts aquests paràmetres els utilitzem per obtenir el nombre d’arbres òptim.

##     oob_err arboles
## 1 0.3226528      10

Obtenim que el nombre d’arbres òptim és de 78.

Utilitzant tots els paràmetres obtinguts generem el model final.

## 
## Call:
##  randomForest(formula = Positivo ~ ., data = train_data_words_df,      mtry = 6, ntree = 78, nodesize = 18, importance = TRUE, norm.votes = TRUE) 
##                Type of random forest: classification
##                      Number of trees: 78
## No. of variables tried at each split: 6
## 
##         OOB estimate of  error rate: 32.21%
## Confusion matrix:
##       FALSE TRUE class.error
## FALSE  3782  416  0.09909481
## TRUE   1766  811  0.68529298

Anem a fer ara la predicció sobre el conjunt de validació utilitzant el model obtingut a partir dels paràmetres òptims.

## [1] 0.6793623
## [1] 0.7025633

Guardarem el valor per comparar-lo amb els altres models.

Un cop obtingut el model òptim per al model de Random Forest, vegem quines són les variables més influents del model i com afecten a la precisió obtinguda.

Observem que les variables formades pels termes “gracias”, “bale”, “feliz”, “grande”, “mejor” són de les més influents. Com la paraula “gracias” destaca sobre de totes les altres. Recordem que aquest fet ja va ser detectat clarament amb el módelo de “Arbres de Classificació”.

Ens preguntem ara què passaria si el nostre model només depengués d’aquestes variables més influents.

## 
## Call:
##  randomForest(formula = Positivo ~ +gracias + bale + feliz + grande +      mejor, data = train_data_words_df, mtry = 6, ntree = 46,      nodesize = 18, importance = TRUE, norm.votes = TRUE) 
##                Type of random forest: classification
##                      Number of trees: 46
## No. of variables tried at each split: 5
## 
##         OOB estimate of  error rate: 32.97%
## Confusion matrix:
##       FALSE TRUE class.error
## FALSE  4053  145  0.03454026
## TRUE   2089  488  0.81063252

Veiem que obtenim un percentatge d’error més gran que utilitzant totes les variables. Atès que volem aconseguir uns valors òptims optarem per utilitzar totes les variables.

3.8. Boosting

Boosting és com hem indicat anteriorment un altre dels mètodes utilitzats per poder trobar el millor equilibri entre biaix i variança.

Aquest model consisteix a ajustar molts models senzills de manera seqüencial i que cada un d’ells tingui en compte els errors de l’anterior. El valor final es obiene prenent la classe més freqüent, de la mateixa manera que en Bagging. D’aquesta manera els models que s’usen en Boosting tenen molt poca variança però molt biaix i considerant molts d’aquests models s’aconsegueix reduir el biaix.

Utilitzem el paquet “caret” amb una graella de diferents valors i Validació Creuada per econtrar els següents paràmetres òptims:

  • interaction.depth: és el nombre de divisions que té l’arbre. El rang de valors que utilitzarem serà: 1, 5 i 10

  • n.trees: es tracta del nombre de models que es generen. En augmentar aquest valor reduïm l’error d’entrenament però generant “overfitting”. Els valors que utilitzarem per al nostre grid seran: 50, 100, 200

  • shrinkage: és el learning rate i atès que en Boosting els models depenen dels valors anteriors, controla la influència de cada un d’ells sobre el total. La idea en referència a aquest paràmetre és optar per valors petits ja qu és preferible un model amb molts passos, però cada un d’ells amb una menor influència que per pocs passos. Els valors utilitzats són: 0.005, 0.05, 0.5

  • n.minobsinnode: és el nombre d’observacions mínim per poder ser dividit. Els valors utilitzats són: 1, 10, 20

Obtenim que la millor combinació de paràmetres és la següent:

##    n.trees interaction.depth shrinkage n.minobsinnode
## 45     200                 5      0.05             20

El millor valor de precisió obtingut a través de Validació Creuada és el següent:

## [1] 0.6823617

Si fem la predicció sobre el conjunt de validació obtenim el següent valor:

## [1] 0.6944198

Guardarem aquest valor per poder comparar-lo.

3.9. Extreme Gradient Boosting

XGBoost és una de les implementacions del concepte Gradient Boosting i utilitza la mateixa filosofia de classificadors febles que aporten la informació dels errors als models posteriors. Però el que fa que XGBoost sigui únic és que utilitza una formalització de model més regularitzada per controlar el “overfitting”, el que li dóna un millor rendiment. La implementació de XGBoost ofereix diverses característiques avançades per a l’ajust de models i admet un ajust detallat i l’addició de paràmetres de regularització.

Per aplicar el model de “Extreme Gradient Boosting” utilitzarem el paquet “caret” i mitjançant TuneGrid i TrainControl de Validació Creuada de 5 folds ajustarem els següents paràmetres:

  • nrounds : El nombre màxim d’iteracions (nombre d’arbres al model final). Els valors utilitzats són 100,350

  • colsample_bytree : El nombre de característiques, expressades com una proporció, a mostrejar quan es construeix un arbre. És el nombre de variables aleatòries que se li proporciona a cada nou arbre. El valor per omissió és 1 (100% de les característiques). El valor que utilitzarem és de 0.75.

  • min_child_weight : El pes mínim en els arbres que estan sent generats. El valor per defecte és 1. Els valors que utilitzem són 0, 0.5, 1

  • eta </ b>: Taxa d’aprenentatge, que és la contribució de cada arbre a la solució. El valor per omissió és 0.3. Els valors que hem utilitzat són 0.05, 0.1, 0.5.

  • gamma : Reducció de pèrdua mínima requerida per fer una altra partició en un arbre. Utilitzem 0.01 com a valor en el nostre Grid.

  • subsample : Relació d’observacions de dades. El valor per omissió és 1 (100%). Utilitzarem 0.5.

  • max_depth : Màxima profunditat dels arbres individuals. Utiliaremos els valors 4,6,10.

## + Fold1: eta=0.05, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold1: eta=0.05, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold1: eta=0.05, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold1: eta=0.05, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold1: eta=0.05, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold1: eta=0.05, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold1: eta=0.10, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold1: eta=0.10, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold1: eta=0.10, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold1: eta=0.10, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold1: eta=0.10, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold1: eta=0.10, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold1: eta=0.50, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold1: eta=0.50, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold1: eta=0.50, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold1: eta=0.50, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold1: eta=0.50, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold1: eta=0.50, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold2: eta=0.05, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold2: eta=0.05, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold2: eta=0.05, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold2: eta=0.05, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold2: eta=0.05, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold2: eta=0.05, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold2: eta=0.10, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold2: eta=0.10, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold2: eta=0.10, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold2: eta=0.10, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold2: eta=0.10, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold2: eta=0.10, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold2: eta=0.50, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold2: eta=0.50, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold2: eta=0.50, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold2: eta=0.50, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold2: eta=0.50, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold2: eta=0.50, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold3: eta=0.05, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold3: eta=0.05, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold3: eta=0.05, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold3: eta=0.05, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold3: eta=0.05, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold3: eta=0.05, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold3: eta=0.10, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold3: eta=0.10, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold3: eta=0.10, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold3: eta=0.10, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold3: eta=0.10, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold3: eta=0.10, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold3: eta=0.50, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold3: eta=0.50, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold3: eta=0.50, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold3: eta=0.50, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold3: eta=0.50, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold3: eta=0.50, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold4: eta=0.05, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold4: eta=0.05, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold4: eta=0.05, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold4: eta=0.05, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold4: eta=0.05, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold4: eta=0.05, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold4: eta=0.10, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold4: eta=0.10, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold4: eta=0.10, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold4: eta=0.10, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold4: eta=0.10, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold4: eta=0.10, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold4: eta=0.50, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold4: eta=0.50, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold4: eta=0.50, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold4: eta=0.50, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold4: eta=0.50, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold4: eta=0.50, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold5: eta=0.05, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold5: eta=0.05, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold5: eta=0.05, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold5: eta=0.05, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold5: eta=0.05, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold5: eta=0.05, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold5: eta=0.10, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold5: eta=0.10, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold5: eta=0.10, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold5: eta=0.10, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold5: eta=0.10, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold5: eta=0.10, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold5: eta=0.50, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold5: eta=0.50, max_depth= 4, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold5: eta=0.50, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold5: eta=0.50, max_depth= 6, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## + Fold5: eta=0.50, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## - Fold5: eta=0.50, max_depth=10, gamma=0.01, colsample_bytree=0.75, min_child_weight=0, subsample=0.5, nrounds=350 
## Aggregating results
## Selecting tuning parameters
## Fitting nrounds = 100, max_depth = 4, eta = 0.05, gamma = 0.01, colsample_bytree = 0.75, min_child_weight = 0, subsample = 0.5 on full training set

A continuació obtindrem el model final que amb els paràmetres indicats ofereix millors resultats.

## ##### xgb.Booster
## raw: 94.3 Kb 
## call:
##   xgboost::xgb.train(params = list(eta = param$eta, max_depth = param$max_depth, 
##     gamma = param$gamma, colsample_bytree = param$colsample_bytree, 
##     min_child_weight = param$min_child_weight, subsample = param$subsample), 
##     data = x, nrounds = param$nrounds, verbose = FALSE, objective = "binary:logistic")
## params (as set within xgb.train):
##   eta = "0.05", max_depth = "4", gamma = "0.01", colsample_bytree = "0.75", min_child_weight = "0", subsample = "0.5", objective = "binary:logistic", silent = "1"
## xgb.attributes:
##   niter
## # of features: 60 
## niter: 100
## nfeatures : 60 
## xNames : Positivo día gracias menos hoy madrid grande ser congreso días gran ahora mundo sin puede siempre copa españa ver noche dos hace así nuevo vía años nada vez bien bueno tan buenos gobierno solo rajoy final mas mejor rey vamos equipo partido año pues cosas feliz barcelona real barça rubalcaba aquí psoe mañana dice hacer portada contra messi ramos bale 
## problemType : Classification 
## tuneValue :
##    nrounds max_depth  eta gamma colsample_bytree min_child_weight subsample
## 1     100         4 0.05  0.01             0.75                0       0.5
## obsLevels : No Yes 
## param :
##  $verbose
## [1] FALSE

Realitzem la predicció sobre el conjunt de validació.

## [1] 0.6842234

Veiem com tot i la potència d’aquest algoritme sembla que no obtenim el valor més alt de precisió. Guardarem el valor per comparar-lo amb els altres models

Un altre mètode per mesurar el rendiment en la classificació binària a més de la precisió és el mètode ROC. A diferència de la precisió, l’anàlisi ROC utilitza la taxa de veritables positius (TPR) i la taxa de falsos positius (FPR). TPR és la proporció positiva classificada correctament (TP / P) i la taxa de falsos positius (FPR) es calcula per 1-TNR (TN / N). La regió ROC mostra la taxa de veritables postivos (TPR) contra la taxa de falsos positius (FPR).

##      Model      Area      p.value binorm.area
## 1 Model  1 0.6253007 2.059215e-27          NA

Com podem veure el model pot diferenciar entre Tweets Positius i no Positius però si ens fixem en el Àrea Under Curve (AUC) veiem que el valor obtingut és d’un 65%.

El coeficient de GINI mesura la desigualtat entre els valors d’una distribució. Un coeficient de Gini de zero expressa una igualtat perfecta, d’altra banda, el coeficient de Gini d’1 (100%) expressa la màxima desigualtat entre els valors.

## [1] 0.270966

En el nostre cas veiem com el coeficient de GINI expressa una desigualtat de 38%. Hi ha una relació entre el coeficient de GINI i el AUC però atès que en aquesta pràctica ens hem centrat en la precisió (ACC) no utilitzarem aquests valors.

Il·lustrem a continuació la importància de les variables segons el model XGB. Veiem com el terme “gràcies” destaca per sobre de les altres i com coincideixen en la gran majoria amb la importància vista en el model de Boosting.

3.10. Support Vector Machines

“Support Vector Machine” (SVM) és un algoritme supervisat d’aprenentatge automàtic que s’utilitza principalment en problemes de classificació.Va ser desenvolupat en la dècada dels 90, dins del camp de la ciència computacional. Si bé es va desenvolupar de manera original com a mètode de classificació binària, la seva aplicació ha estat estesa a problemes de classificació múltiple i de regressió. Els algoritmes de SVM han resultat ser un dels millors classificadors per a un ampli ventall de situacions, pel que s’anomena un referent dins de l’àmbit d’aprenentatge estadístic i d’aprenentatge automàtic. En aquest algoritme, representem cada element de dades com a punt en un espai n-dimensional (on n és el nombre de característiques que tenim) i el valor de cada característica és el valor d’una coordenada particular. A continuació, es realitza la classificació trobant l’hiperplà que diferencia les diferents classes de la millor manera. Aquesta tasca es realitza maximitzant les distàncies entre els punts més propers de cada clase per aconseguir l’hiperplà òptim de separació.

És relativament fàcil obtenir un hiplerplà lineal entre dues clases però, què passa si la separació entre dues classes no és lineal? Per resoldre aquest problema SVM disposa de funcions de kernel que permeten transformar un espai no lineal i dificilment separable en un espai lineal i separable. Es disposa de diferents tipus de kernels per transformar la informació però en aquest TFM compararem el lineal i el radial.

En aquest algoritme és necessari convertir la variable depenent en categòrica. Recordem que fin el moment havíem treballat amb la variable “positivo” de manera qualitativa. A continuació, emprarem el paquet caret que permet definir una matriu de control per aplicar l’algoritme de SVM amb la tècnica de la “validació creuada”. En el nostre cas el mètode que emprarem serà “repeatedcv” amb un fold de tamany 10 i 3 repeticions. SVM disposa també d’un paràmetre de preProcess() que permet indicar la normalitzar les dades a tractar. En el nostre cas, el valor d’aquest paràmetre serà de “center,scale”, valors que indiquen que les nostres dades es convertiran per tenir una mitja 0 i una desviació estàndar de 1.

El model obtingut és el següent:

## Support Vector Machines with Linear Kernel 
## 
## 6775 samples
##   59 predictor
##    2 classes: 'No', 'Yes' 
## 
## Pre-processing: centered (59), scaled (59) 
## Resampling: Cross-Validated (10 fold, repeated 3 times) 
## Summary of sample sizes: 6098, 6098, 6097, 6097, 6098, 6098, ... 
## Resampling results:
## 
##   Accuracy   Kappa    
##   0.6782762  0.2345992
## 
## Tuning parameter 'C' was held constant at a value of 1

A continuació realitzarem la predicció

## [1] 0.6979628

Veim com el valor obtingut és elevat comparat amb els altres algoritmes. Anem a veure ara si aquest valor es pot millorar. Per això el que farem serà emprar una graella de valors (tuneGrid) per trobar el valor de l’hiperparàmetre C òptim.

## Support Vector Machines with Linear Kernel 
## 
## 6775 samples
##   59 predictor
##    2 classes: 'No', 'Yes' 
## 
## Pre-processing: centered (59), scaled (59) 
## Resampling: Cross-Validated (10 fold, repeated 3 times) 
## Summary of sample sizes: 6099, 6097, 6098, 6097, 6097, 6098, ... 
## Resampling results:
## 
##   Accuracy   Kappa    
##   0.6783804  0.2319175
## 
## Tuning parameter 'C' was held constant at a value of 0.01

A continuació es pot observar la gràfica obtinguda per diferents valors de l’hiperparàmetre C. Veim com el valor òptim correspon a C=0.01

Emprarem el model amb aquest valor per realitzar la predicció.

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   No  Yes
##        No  1261  604
##        Yes  138  255
##                                           
##                Accuracy : 0.6714          
##                  95% CI : (0.6516, 0.6908)
##     No Information Rate : 0.6196          
##     P-Value [Acc > NIR] : 1.716e-07       
##                                           
##                   Kappa : 0.2214          
##  Mcnemar's Test P-Value : < 2.2e-16       
##                                           
##             Sensitivity : 0.9014          
##             Specificity : 0.2969          
##          Pos Pred Value : 0.6761          
##          Neg Pred Value : 0.6489          
##              Prevalence : 0.6196          
##          Detection Rate : 0.5585          
##    Detection Prevalence : 0.8260          
##       Balanced Accuracy : 0.5991          
##                                           
##        'Positive' Class : No              
## 
## [1] 0.7037201

El valor obtingut és el més alt fins al moment. Però encara ens queda explorar la versió corresponent al kernel radial. Realitzarem el mateix procés que abans. Primer amb un trainControl basat en CV.

## Support Vector Machines with Radial Basis Function Kernel 
## 
## 6775 samples
##   59 predictor
##    2 classes: 'No', 'Yes' 
## 
## Pre-processing: centered (59), scaled (59) 
## Resampling: Cross-Validated (10 fold, repeated 3 times) 
## Summary of sample sizes: 6097, 6098, 6097, 6097, 6097, 6097, ... 
## Resampling results:
## 
##   Accuracy   Kappa    
##   0.6667676  0.1884172
## 
## Tuning parameter 'sigma' was held constant at a value of 0.01331258
## 
## Tuning parameter 'C' was held constant at a value of 0.25

Un cop obtingut el model realitzar la predicció.

## [1] 0.6505757

El valor obtingut no és tan elevat com l’obtingut amb el kernel lineal. De fet, és dels més baixos.

Emprarem a continuació un tuneGrid per trobar els valors òptims dels hiperparàmetres “sigma” i “C”.

## Support Vector Machines with Radial Basis Function Kernel 
## 
## 6775 samples
##   59 predictor
##    2 classes: 'No', 'Yes' 
## 
## Pre-processing: centered (59), scaled (59) 
## Resampling: Cross-Validated (10 fold, repeated 3 times) 
## Summary of sample sizes: 6098, 6098, 6098, 6098, 6098, 6097, ... 
## Resampling results across tuning parameters:
## 
##   sigma  C     Accuracy   Kappa
##   0.00   0.00        NaN  NaN  
##   0.00   0.01  0.6196311    0  
##   0.01   0.00        NaN  NaN  
##   0.01   0.01  0.6196311    0  
## 
## Accuracy was used to select the optimal model using the largest value.
## The final values used for the model were sigma = 0.01 and C = 0.01.

La gràfica obtinguda ens indica els nivells de precisió obtinguts per diferents valors de “C” i “Sigma”

## [1] 0.6695748

Veim com el resultat no millora molt del resultat obtingut anteriorment.

4. Comparativa

Un cop ja hem realitzat la generació dels models en el nostre conjunt de Training i les prediccions en el nostre conjunt de Validació, compararem els valors de precisió en la classificació dels diferents models estudiats.

Obtenim que el millor model és SVM.

5. Model Final

A continuació aplicarem el millor model obtingut a un nou conjunt de Training format pels antics conjunts de Training i Validació i aplicarem la predicció a un conjunt de Test que els nostres models encara no han vist.

El nombre d’observacions dels nostres nous conjunts de Training i Test són els següents:

## [1] 9033   60
## [1] 2257   60

Podria passar que en ampliar el conjunt de dades dels valors òptims que hem calculat anteriorment per al model de SVM ja no fossin els mateixos. Per a això aplicarem Validació Creuada amb els mateixos rangs de valors que els aplicats anteriorment per obtenir la configuració òptima de paràmetres.

## Support Vector Machines with Linear Kernel 
## 
## 9033 samples
##   59 predictor
##    2 classes: 'FALSE', 'TRUE' 
## 
## Pre-processing: centered (59), scaled (59) 
## Resampling: Cross-Validated (10 fold, repeated 3 times) 
## Summary of sample sizes: 8130, 8129, 8129, 8130, 8129, 8130, ... 
## Resampling results across tuning parameters:
## 
##   C     Accuracy   Kappa    
##   0.01  0.6762632  0.2269444
##   0.02  0.6776651  0.2317013
## 
## Accuracy was used to select the optimal model using the largest value.
## The final value used for the model was C = 0.02.

Obtenim que els paràmetres òptims són els següents:

##      C
## 2 0.02

El millor valor de precisió obtingut a través de Validació Creuada en el nou conjunt de Training és el següent:

##      C  Accuracy     Kappa AccuracySD    KappaSD
## 1 0.01 0.6762632 0.2269444 0.01236116 0.02950619
## 2 0.02 0.6776651 0.2317013 0.01318094 0.03190018
## [1] 0.6776651

Finalment, vam realitzar la predicció sobre el conjunt de test.

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction FALSE TRUE
##      FALSE  1156  711
##      TRUE    243  147
##                                           
##                Accuracy : 0.5773          
##                  95% CI : (0.5566, 0.5978)
##     No Information Rate : 0.6198          
##     P-Value [Acc > NIR] : 1               
##                                           
##                   Kappa : -0.0026         
##  Mcnemar's Test P-Value : <2e-16          
##                                           
##             Sensitivity : 0.8263          
##             Specificity : 0.1713          
##          Pos Pred Value : 0.6192          
##          Neg Pred Value : 0.3769          
##              Prevalence : 0.6198          
##          Detection Rate : 0.5122          
##    Detection Prevalence : 0.8272          
##       Balanced Accuracy : 0.4988          
##                                           
##        'Positive' Class : FALSE           
## 
## Accuracy 
## 0.577315
## [1] 0.577315

6. Conclusiones

En aquesta pràctica hem comparat un total de 8 models de classificació per obtenir el que ens proporcionés millors resultats de precisió sobre Tweet correctament classificats com a positius. Per a això hemo seguit els criteris de divisió del conjunt de dades en Training, Validació i Test i hem aplicat Validació Creuada per optimitzar els paràmetres dels models que ho requerien. En comparar tots els models el que millor resultats ha ofert ha estat Boosting.

A continuació hem vist que per a un conjunt de dades de Training de 9000 mostres el millor model ha obtingut una precisió d’un 68%, sent un valor bastant acceptable. Però quan hem utilitzat les observacions reservades per Test el percentatge de classificació correcta ha baixat notablement fins a un 58%. Un valor fins i tot menor que el del model base (62%). Davant d’aquests resultats concloem que malgrat els nostres esforços per trobar un model òptim, seria millor classificar Tweets aleatòriament que aplicant el millor model obtingut.

Possiblement les causes d’aquest valor tan baix en la predicció final siguin les següents:

  • Una mostra de Tweets petita i un coeficient de dispersió petit. Cal considerar que un total de 9.000 Tweets de Training per al model final és un valor relativament petit i que aplicant el coeficient de dispersió de l’1% només hem aconseguit un total de 60 termes que són les variables independents que han de tenir el poder significatiu suficient com per classificar nous Tuits. Com hem vist el poder significatiu d’aquests termes no és suficient.

  • La complexitat de modelar el llenguatge natural. Un altre punt a considerar per donar una explicació a tan baix resultat de precisió és la complexitat del llenguatge natural. En aquesta pràctica només hem considerat els termes de manera independent però considerar unes característiques que poguessin contemplar el poder significatiu de la combinació de n-termes (n-grams) podria donar més significat a les variables i major influència a l’hora de predir la polaritat d’un Tweet. En aquest sentit, el tractament de les abreviacions, els emojis, la detecció d’ironies, l’anàlisi de la construcció sintàctica de les paraules, la consideració del valor semàntic dels termes que formen un Tweet o una contextualització dels missatges podria ajudar a obtenir millors resultats.

  • La subjectivitat de la classificació. És important destacar aquest aspecte ja que segons s’ha pogut comprovar revisant el text d’alguns Tweets, aquests han estat classificats d’una manera molt subjectiva i per exemple Tweets que parlessin del Reial Madrid o de Cristina Ronaldo eren classificats com Positius i d’altres que parlessin de Messi o el FC Barcelona eren considerats negatius. Aquests aspectes també han pogut influir en la correcta classificació dels nostres models.

De tota manera, cal indicar que segons les fonts consuladas ( Sentiment Analysis ) els percentatges més elevats que s’han obtingut utilitzant mostres grans i algoritmes més complexos com SVM han estat del 72%. Un percentatge que si bé és elevat, tot i dista d’uns valors que ens permetin assegurar una modelització de la polaritat del llenguatge natural d’una manera que ens permeti unes certes garanties d’encert.

En qualsevol cas, hem desenvolupat la comparativa de diferents models predictius de classificació, l’estructura de la qual ens pot servir en futurs treballs per obtenir millors resultats aportant noves característiques com els n-grams que ajudin a obtenir major significació a les variables.